//! Rocket 完整服务器示例
//! 展示如何使用 unified_api 框架构建完整的 Rocket 应用

#[cfg(feature = "rocket")]
mod rocket_impl {
    use rocket::{get, post, put, delete, routes, State, Response, Request, http::Status};
    use rocket::fairing::{Fairing, Info, Kind};
    use rocket::data::{ToByteUnit, Data};
    use rocket::serde::{json::Json, Deserialize, Serialize};
    use std::sync::Arc;
    
    use unified_api::{
        uni_api, auth::{JwtAuthPolicy, AuthPolicy, AuthContext, AuthRequest, AuthResult},
        routers::{RouteInfo, RouteBuilder},
        middleware::{AuthMiddleware, MiddlewareChain, LoggingMiddleware, CorsMiddleware},
        swagger::{SwaggerConfig, SwaggerGenerator}
    };

    #[derive(Debug, Serialize, Deserialize, Clone)]
    struct User {
        id: u64,
        name: String,
        email: String,
        created_at: String,
    }

    #[derive(Debug, Serialize, Deserialize)]
    struct CreateUserRequest {
        name: String,
        email: String,
    }

    #[derive(Debug, Serialize, Deserialize)]
    struct UpdateUserRequest {
        name: Option<String>,
        email: Option<String>,
    }

    #[derive(Debug, Serialize)]
    struct ApiResponse<T> {
        success: bool,
        data: Option<T>,
        message: Option<String>,
        error: Option<String>,
    }

    impl<T> ApiResponse<T> {
        fn success(data: T) -> Self {
            Self {
                success: true,
                data: Some(data),
                message: None,
                error: None,
            }
        }

        fn success_with_message(data: T, message: &str) -> Self {
            Self {
                success: true,
                data: Some(data),
                message: Some(message.to_string()),
                error: None,
            }
        }

        fn error(message: &str) -> Self {
            Self {
                success: false,
                data: None,
                message: None,
                error: Some(message.to_string()),
            }
        }
    }

    // 模拟用户数据库
    struct UserDatabase {
        users: std::sync::RwLock<Vec<User>>,
    }

    impl UserDatabase {
        fn new() -> Self {
            let users = vec![
                User {
                    id: 1,
                    name: "Alice Johnson".to_string(),
                    email: "alice@example.com".to_string(),
                    created_at: "2024-01-01T00:00:00Z".to_string(),
                },
                User {
                    id: 2,
                    name: "Bob Smith".to_string(),
                    email: "bob@example.com".to_string(),
                    created_at: "2024-01-02T00:00:00Z".to_string(),
                },
            ];
            
            Self {
                users: std::sync::RwLock::new(users),
            }
        }

        fn get_all(&self) -> Vec<User> {
            self.users.read().unwrap().clone()
        }

        fn get_by_id(&self, id: u64) -> Option<User> {
            self.users.read().unwrap().iter().find(|u| u.id == id).cloned()
        }

        fn create(&self, request: CreateUserRequest) -> User {
            let mut users = self.users.write().unwrap();
            let new_id = users.len() as u64 + 1;
            let user = User {
                id: new_id,
                name: request.name,
                email: request.email,
                created_at: chrono::Utc::now().to_rfc3339(),
            };
            users.push(user.clone());
            user
        }

        fn update(&self, id: u64, request: UpdateUserRequest) -> Option<User> {
            let mut users = self.users.write().unwrap();
            if let Some(user) = users.iter_mut().find(|u| u.id == id) {
                if let Some(name) = request.name {
                    user.name = name;
                }
                if let Some(email) = request.email {
                    user.email = email;
                }
                Some(user.clone())
            } else {
                None
            }
        }

        fn delete(&self, id: u64) -> bool {
            let mut users = self.users.write().unwrap();
            let initial_len = users.len();
            users.retain(|u| u.id != id);
            users.len() < initial_len
        }
    }

    // API处理器
    #[uni_api(
        route = "/users",
        method = "GET",
        auth_policy = "permission:users.read",
        description = "获取所有用户列表",
        tags = ["users", "admin"]
    )]
    #[get("/users")]
    async fn get_users(db: &State<Arc<UserDatabase>>) -> Json<ApiResponse<Vec<User>>> {
        let users = db.get_all();
        Json(ApiResponse::success(users))
    }

    #[uni_api(
        route = "/users/<id>",
        method = "GET",
        auth_policy = "permission:users.read",
        description = "根据ID获取用户信息",
        tags = ["users"]
    )]
    #[get("/users/<id>")]
    async fn get_user_by_id(
        id: u64,
        db: &State<Arc<UserDatabase>>,
    ) -> Result<Json<ApiResponse<User>>, Status> {
        match db.get_by_id(id) {
            Some(user) => Ok(Json(ApiResponse::success(user))),
            None => Err(Status::NotFound),
        }
    }

    #[uni_api(
        route = "/users",
        method = "POST",
        auth_policy = "permission:users.create",
        description = "创建新用户",
        tags = ["users", "admin"]
    )]
    #[post("/users", data = "<user_data>")]
    async fn create_user(
        user_data: Json<CreateUserRequest>,
        db: &State<Arc<UserDatabase>>,
    ) -> Json<ApiResponse<User>> {
        let user = db.create(user_data.into_inner());
        Json(ApiResponse::success_with_message(user, "User created successfully"))
    }

    #[uni_api(
        route = "/users/<id>",
        method = "PUT",
        auth_policy = "user:{id}",
        description = "更新用户信息",
        tags = ["users"]
    )]
    #[put("/users/<id>", data = "<user_data>")]
    async fn update_user(
        id: u64,
        user_data: Json<UpdateUserRequest>,
        db: &State<Arc<UserDatabase>>,
    ) -> Result<Json<ApiResponse<User>>, Status> {
        match db.update(id, user_data.into_inner()) {
            Some(user) => Ok(Json(ApiResponse::success_with_message(user, "User updated successfully"))),
            None => Err(Status::NotFound),
        }
    }

    #[uni_api(
        route = "/users/<id>",
        method = "DELETE",
        auth_policy = "role:admin",
        description = "删除用户",
        tags = ["users", "admin"]
    )]
    #[delete("/users/<id>")]
    async fn delete_user(
        id: u64,
        db: &State<Arc<UserDatabase>>,
    ) -> Result<Json<ApiResponse<()>>, Status> {
        if db.delete(id) {
            Ok(Json(ApiResponse::success_with_message((), &format!("User {} deleted successfully", id))))
        } else {
            Err(Status::NotFound)
        }
    }

    #[uni_api(
        route = "/health",
        method = "GET",
        auth_policy = "",
        description = "健康检查接口",
        tags = ["health"]
    )]
    #[get("/health")]
    async fn health_check() -> Json<ApiResponse<serde_json::Value>> {
        let health_data = serde_json::json!({
            "status": "healthy",
            "timestamp": chrono::Utc::now().to_rfc3339(),
            "version": "1.0.0"
        });
        Json(ApiResponse::success(health_data))
    }

    // Swagger文档接口
    #[get("/docs")]
    async fn swagger_docs() -> Json<serde_json::Value> {
        let config = SwaggerConfig::new("User Management API", "1.0.0")
            .with_description("A comprehensive user management API built with unified_api framework")
            .with_host("localhost:8080")
            .with_base_path("/api");

        let routes = vec![
            RouteInfo::new("/users", "GET", "get_users")
                .with_auth_policy("permission:users.read")
                .with_description("获取所有用户列表")
                .with_tags(vec!["users", "admin"]),
            RouteInfo::new("/users/<id>", "GET", "get_user_by_id")
                .with_auth_policy("permission:users.read")
                .with_description("根据ID获取用户信息")
                .with_tags(vec!["users"]),
            RouteInfo::new("/users", "POST", "create_user")
                .with_auth_policy("permission:users.create")
                .with_description("创建新用户")
                .with_tags(vec!["users", "admin"]),
            RouteInfo::new("/users/<id>", "PUT", "update_user")
                .with_auth_policy("user:{id}")
                .with_description("更新用户信息")
                .with_tags(vec!["users"]),
            RouteInfo::new("/users/<id>", "DELETE", "delete_user")
                .with_auth_policy("role:admin")
                .with_description("删除用户")
                .with_tags(vec!["users", "admin"]),
            RouteInfo::new("/health", "GET", "health_check")
                .with_auth_policy("")
                .with_description("健康检查接口")
                .with_tags(vec!["health"]),
        ];

        let generator = SwaggerGenerator::new(config).add_routes(routes);
        
        match generator.generate() {
            Ok(swagger_doc) => Json(swagger_doc),
            Err(_) => Json(serde_json::json!({
                "error": "Failed to generate Swagger docs"
            })),
        }
    }

    // 认证中间件
    struct AuthFairing;

    #[rocket::async_trait]
    impl Fairing for AuthFairing {
        fn info(&self) -> Info {
            Info {
                name: "Authentication Fairing",
                kind: Kind::Request,
            }
        }

        async fn on_request(&self, request: &mut Request<'_>, _data: &mut Data<'_>) {
            // 跳过健康检查和文档接口的认证
            let path = request.uri().path();
            if path == "/api/health" || path == "/api/docs" {
                return;
            }

            // 检查 Authorization header
            if let Some(auth_header) = request.headers().get_one("Authorization") {
                if auth_header.starts_with("Bearer ") {
                    let token = &auth_header[7..];
                    
                    // 简单的token验证
                    if token == "valid-jwt-token" || token == "admin-token" {
                        return;
                    }
                }
            }

            // 如果没有有效token，设置错误状态
            request.local_cache(|| Status::Unauthorized);
        }
    }

    // 响应中间件
    struct ResponseFairing;

    #[rocket::async_trait]
    impl Fairing for ResponseFairing {
        fn info(&self) -> Info {
            Info {
                name: "Response Fairing",
                kind: Kind::Response,
            }
        }

        async fn on_response<'r>(&self, request: &'r Request<'_>, response: &mut Response<'r>) {
            if let Some(status) = request.local_cache(|| Status::Ok) {
                if *status == Status::Unauthorized {
                    response.set_status(Status::Unauthorized);
                    response.set_header(rocket::http::ContentType::JSON);
                    response.set_sized_body(Some(40), std::io::Cursor::new(
                        serde_json::json!({
                            "success": false,
                            "error": "Unauthorized",
                            "message": "Valid JWT token required"
                        }).to_string()
                    ));
                }
            }
        }
    }

    #[rocket::main]
    pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
        println!("🚀 Starting Rocket server with unified_api framework");
        println!("📚 Swagger docs available at: http://localhost:8080/api/docs");
        println!("🏥 Health check available at: http://localhost:8080/api/health");

        // 初始化用户数据库
        let db = Arc::new(UserDatabase::new());

        // 配置JWT认证策略
        let jwt_secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "your-secret-key".to_string());
        let _auth_policy = Arc::new(JwtAuthPolicy::new(jwt_secret));

        // 配置中间件链
        let _middleware_chain = MiddlewareChain::new()
            .add_middleware(Arc::new(LoggingMiddleware))
            .add_middleware(Arc::new(CorsMiddleware::default()));

        let figment = rocket::Config::figment()
            .merge(("address", "127.0.0.1"))
            .merge(("port", 8081));

        let _rocket = rocket::custom(figment)
            .manage(db)
            .attach(AuthFairing)
            .attach(ResponseFairing)
            .mount("/api", routes![
                get_users,
                get_user_by_id,
                create_user,
                update_user,
                delete_user,
                health_check,
                swagger_docs
            ])
            .launch()
            .await?;

        Ok(())
    }
}

#[cfg(not(feature = "rocket"))]
fn main() {
    println!("This example requires the 'rocket' feature to be enabled.");
    println!("Run with: cargo run --example rocket_server --features rocket,jwt,swagger");
}

#[cfg(feature = "rocket")]
fn main() {
    rocket_impl::main();
}